/*
** $Id: crypter_aes_cbc.c 28 2014-09-17 16:22:40Z chupin007@gmail.com $
** $HeadURL: http://bapps.googlecode.com/svn/trunk/src/enc/src/crypter_aes_cbc.c $
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/aes.h>

AES_KEY stKey;
unsigned char ivec[16];
unsigned char ivec_init[] = {0,1,2,3,4,5,6,7,8,9,0,'a','b','c','d','e'};

unsigned int PadData (unsigned char *ibuf, unsigned int ilen, int blksize)
{
  unsigned int   i; // loop counter
  unsigned char  pad; // pad character (calculated)
  unsigned char *p; // pointer to end of data

  // calculate pad character
  pad = (unsigned char) (blksize - (ilen % blksize));

  // append pad to end of string
  p = ibuf + ilen;
  for (i = 0; i < (int) pad; i++) {
    *p = pad;
    ++p;
  }
  return (ilen + pad);
}

unsigned int NoPadLen (unsigned char *ibuf, unsigned int ilen)
{
  unsigned int   i;			// adjusted length
  unsigned char *p;			// pointer to last character

  p = ibuf + (ilen - 1);
  i = ilen - (unsigned int) *p;
  return (i);
}


void crypterInit( int command, char *key ) {

  if( strlen( key ) < 16 ) {
    fprintf( stderr, "wronng key:len=%d, %s\n", strlen( key ), key );
    exit( 1 );
  }
  if( ! command ) {
    if( AES_set_encrypt_key( key, 128, &stKey ) < 0 ) {
      fprintf( stderr, "AES_set_encrypt_key failed" );
      exit( 1 );
    }
  } else {
    if( AES_set_decrypt_key( key, 128, &stKey ) < 0 ) {
      fprintf( stderr, "AES_set_decrypt_key failed" );
      exit( 1 );
    }
  }

}

int crypterEncrypt( int nfld, char *buff, char *crypted, int len ) {

  memcpy( ivec, ivec_init, sizeof( ivec ) );

#ifdef DIFF_COLUMN_IV
  ivec[0] = nfld;
#endif

  len = PadData ( buff, len, 16 );
  AES_cbc_encrypt( buff, crypted, len, &stKey, ivec, AES_ENCRYPT);
  return len;

}

int crypterDecrypt( int nfld, char *crypted, char *buff, int len ) {

  memcpy( ivec, ivec_init, sizeof( ivec ) );

#ifdef DIFF_COLUMN_IV
  ivec[0] = nfld;
#endif

  AES_cbc_encrypt( crypted, buff, len, &stKey, ivec, AES_DECRYPT );
  buff [NoPadLen (buff, len)] = 0x00;
  return len;

}
